/*
 * TraceInfoRecorder.c
 *
 *  Created on: 2012/08/02
 *      Author: guanxiaoying
 */
#include "../tracedef.h"
#include "../../table/core_table.h"
#include "trace_cmd.h"

static VOID tr_RecLimitedScp( AST astCmd );

static VOID tr_ResLoggingRestore( AST astCmdList,
		AST astParam, U4 flag ){
	AST astLog;
	AST astPreLog;
	AST astType;
	TRVALUESCP stValueScp;

	if( flag & VARI_CHANGED ){
		astType = LinkVariable.getType( stTrVariableAccess.variable.get( astParam ));
		Tr_ScpGetScpByType( astType, &stValueScp );
	}else{
		astType = LinkFunction.getType( stTrFunctionAccess.function.get( astParam ) );
		astType = LinkTypeInfo.getElementType( astType );
		Tr_ScpGetScpByType( astType, &stValueScp );
	}
	astPreLog = stCmdListMetaAccess.logging.get( astCmdList );
	stValScpChangingLogAccess.alloc(1);
	astLog = stValScpChangingLogAccess.getMax();
	stValScpChangingLogAccess.flag.set( astLog, flag );
	stValScpChangingLogAccess.param.set( astLog, astParam );
	stValScpChangingLogAccess.setValueScope( astLog,  &stValueScp );
	stValScpChangingLogAccess.setNegValueScope( astLog,  &stValueScp );
	stValScpChangingLogAccess.times.set( astLog,
			stCmdPathInfoAccess.totalTimes.get( stCmdCurrTraceInfo.astPath ) + 1 );
	if( astPreLog ){
		stValScpChangingLogAccess.next.set( astLog, astPreLog );
	}
	stCmdListMetaAccess.logging.set( astCmdList, astLog );
}
static VOID tr_ResLoggingNewScope( AST astCmdList,
		AST astParam, U4 flag, TRVALUESCP *scp, TRVALUESCP *negScp ){
	AST astLog;
	AST astPreLog;
	stValScpChangingLogAccess.alloc(1);
	astLog = stValScpChangingLogAccess.getMax();
	stValScpChangingLogAccess.flag.set( astLog, flag );
	stValScpChangingLogAccess.param.set( astLog, astParam );
	if( scp != NULL ){
		stValScpChangingLogAccess.setValueScope( astLog, scp );
	}
	if( negScp != NULL ){
		stValScpChangingLogAccess.setNegValueScope( astLog, negScp );
	}
	astPreLog = stCmdListMetaAccess.logging.get( astCmdList );
	if( astPreLog ){
		stValScpChangingLogAccess.next.set( astLog, astPreLog );
	}
	stCmdListMetaAccess.logging.set( astCmdList, astLog );
	stValScpChangingLogAccess.times.set( astLog,
			stCmdPathInfoAccess.totalTimes.get( stCmdCurrTraceInfo.astPath ) + 1 );
}
static BOOL tr_RecIsReferred( AST astTrVari, AST astOperand, BOOL bCalcuted ){
	AST astCmdList;
	if( !LinkOperand.isCommandList( astOperand )){
		if( astTrVari > 0
			&& Tr_VariGetVari( astTrVari ) == Tr_OpeGetTempVari( astOperand ) ){
			return bCalcuted;
		}else{
			return FALSE;
		}
	}
	astCmdList = LinkOperand.getParameter( astOperand );
	switch(stCmdListAccess.opKind.get( astCmdList )){
	case ASM_CMD_GETOPERAND  :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getLeftOperand( astCmdList),
				bCalcuted );
	case ASM_CMD_GETOFFSET_UNIT   :
	case ASM_CMD_GETOFFSET    :
	case ASM_CMD_GETMEMDATA   :
	case ASM_CMD_GETADDR  :
		return FALSE;
	case ASM_CMD_MINUS  :
	case ASM_CMD_NEGATION :
	case ASM_CMD_BITNEGATION :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getLeftOperand( astCmdList),
				TRUE );
	case ASM_CMD_CALL  :
		return FALSE;
	case ASM_CMD_INC  :
		return FALSE;
	case ASM_CMD_DEC  :
		return FALSE;
	case ASM_CMD_CAST   :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getRightOperand( astCmdList),
				bCalcuted );
	case ASM_CMD_MUL   :
	case ASM_CMD_DIV   :
	case ASM_CMD_MOD   :
	case ASM_CMD_ADD  :
	case ASM_CMD_SUB  :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getLeftOperand( astCmdList),
				    TRUE ) ||
				tr_RecIsReferred( astTrVari, LinkCommandList.getRightOperand( astCmdList),
						TRUE );
	case ASM_CMD_LSFT   :
	case ASM_CMD_RSFT   :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getLeftOperand( astCmdList),
				    TRUE ) ||
				tr_RecIsReferred( astTrVari, LinkCommandList.getRightOperand( astCmdList),
						TRUE );
	case ASM_CMD_GREATER   :
	case ASM_CMD_GREATEREQUAL   :
	case ASM_CMD_LESS   :
	case ASM_CMD_LESSEQUAL   :
		return FALSE;
	case ASM_CMD_EQUAL   :
	case ASM_CMD_UNEQUAL   :
		return FALSE;
	case ASM_CMD_BITAND   :
	case ASM_CMD_BITEXOR   :
	case ASM_CMD_BITINOR  :
		return FALSE;
	case ASM_CMD_LGAND   :
	case ASM_CMD_LGOR   :
		return FALSE;
	case ASM_CMD_ASSIGN   :
		return tr_RecIsReferred( astTrVari, LinkCommandList.getRightOperand( astCmdList),
				bCalcuted );
	case ASM_CMD_ASSIGNARG   :
		return FALSE;
	}
	return FALSE;
}
static BOOL tr_RecIsRecursive( AST astTrVari, AST astCmdList ){
	AST astOperand;

	astOperand = LinkCommandList.getRightOperand( astCmdList );

	if( LinkOperand.isCommandList( astOperand )){
		return tr_RecIsReferred( astTrVari, astOperand, FALSE );
	}
	return FALSE;
}
static S4 tr_RecCmdList_Ret( VOID ){
	TRVALUESCP stVarScope;
	AST astOperand;

	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	if( astOperand > 0 ){

		Tr_ScpGetOperandValue( astOperand, &stVarScope );
		if( Tr_FuncIsInTracing( stCmdCurrTraceInfo.astFunction ) ){
			tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable,
					stCmdCurrTraceInfo.astFunction,
					FUNCTION_CHANGED_BY_RET,
					&stVarScope,
					&stVarScope );
			Tr_FuncMergeReturnValue(  stCmdCurrTraceInfo.astFunction, &stVarScope );
		}else{
			tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable,
					stCmdCurrTraceInfo.astFunction,
					FUNCTION_CHANGED_BY_MERGE,
					&stVarScope,
					&stVarScope );
			Tr_FuncSetReturnValue(  stCmdCurrTraceInfo.astFunction, &stVarScope );
		}
	}
	return TRACEEXIT_SUCCESS;
}
static S4 tr_RecCmdList_Unary( VOID ){
	U4 kind = stCmdListAccess.opKind.get( stCmdCurrTraceInfo.astTable );
	AST astOperand;
	AST astTempVari;
	AST astTrVari;

	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	astTempVari = Tr_OpeGetTempVari( astOperand );
	if( astTempVari > 0 ){
		astTrVari = Tr_VarBlkGetVariOrAdd( astTempVari, Tr_PathParamGetCurrVariBlock() );
	}
	switch(kind){
	case ASM_CMD_GETMEMDATA   :
		/* indirection reference. Read. do nothing */
		break;
	case ASM_CMD_GETADDR  :
		/* get memory address. may be referred indirectly. treat as write */
		if( Tr_VariNeedCalcuteScp( astTrVari ) ){
			tr_ResLoggingRestore( stCmdCurrTraceInfo.astTable, astTrVari, VARI_CHANGED_BY_ADDR_RESTORE );
			Tr_VariResetScope( astTrVari );
		}
		break;
	case ASM_CMD_MINUS  :
		/* Read. do nothing */
		break;
	case ASM_CMD_NEGATION :
		/* Read. do nothing */
		break;
	case ASM_CMD_BITNEGATION :
		/* Read. do nothing */
		break;
	}
	return TRACEEXIT_SUCCESS;
}
static S4 tr_RecCmdList_Primary( VOID ){
	AST astOperand;
	AST astTempVari;
//	AST astTrVari;
	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	astTempVari = Tr_OpeGetTempVari( astOperand );
	if( astTempVari > 0 ){
		/*astTrVari =*/ Tr_VarBlkGetVariOrAdd( astTempVari, Tr_PathParamGetCurrVariBlock() );
	}
	return TRACEEXIT_SUCCESS;
}
static S4 tr_RecCmdList_Inc( VOID ){
	AST astOperand;
	AST astTempVari;
	AST astTrVari;
	TRVALUESCP scp;

	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	astTempVari = Tr_OpeGetTempVari( astOperand );
	if( astTempVari > 0 ){
		astTrVari = Tr_VarBlkGetVariOrAdd( astTempVari, Tr_PathParamGetCurrVariBlock() );
		if( Tr_VariNeedCalcuteScp( astTrVari ) ){
			if ( Tr_PathIsInLoop() ){
				if( !Tr_VariIsLoopCnter( astTrVari ) ){
					Tr_VariResetScope( astTrVari );
					tr_ResLoggingRestore( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_INLOOP_RESTORE );
				}else{
					Tr_VariGetScope( astTrVari, &scp );
					Tr_ScpIncrement( &scp, &scp );
					Tr_VariSetScope( astTrVari, &scp );
					tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
				}
			}else{
				Tr_VariGetScope( astTrVari, &scp );
				Tr_ScpIncrement( &scp, &scp );
				Tr_VariSetScope( astTrVari, &scp );
				tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
			}
		}
	}
	return TRACEEXIT_SUCCESS;
}
static S4 tr_RecCmdList_Dec( VOID ){
	AST astOperand;
	AST astTempVari;
	AST astTrVari;
	TRVALUESCP scp;
	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	astTempVari = Tr_OpeGetTempVari( astOperand );
	if( astTempVari > 0 ){
		astTrVari = Tr_VarBlkGetVariOrAdd( astTempVari, Tr_PathParamGetCurrVariBlock() );
		if( Tr_VariNeedCalcuteScp( astTrVari ) ){
			if ( Tr_PathIsInLoop() ){
				if( !Tr_VariIsLoopCnter( astTrVari ) ){
					Tr_VariResetScope( astTrVari );
					tr_ResLoggingRestore( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_INLOOP_RESTORE );
				}else{
					Tr_VariGetScope( astTrVari, &scp );
					Tr_ScpDecrement( &scp, &scp );
					Tr_VariSetScope( astTrVari, &scp );
					tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
				}
			}else{
				Tr_VariGetScope( astTrVari, &scp );
				Tr_ScpDecrement( &scp, &scp );
				Tr_VariSetScope( astTrVari, &scp );
				tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
			}
		}
	}
	return TRACEEXIT_SUCCESS;
}

static S4 tr_RecCmdList_Assign( VOID ){
	AST astOperand;
	AST astTempVari;
	AST astTrVari;
	TRVALUESCP scp;
	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	astTempVari = Tr_OpeGetTempVari( astOperand );
	if( astTempVari > 0 ){
		astTrVari = Tr_VarBlkGetVariOrAdd( astTempVari, Tr_PathParamGetCurrVariBlock() );
		if( Tr_VariNeedCalcuteScp( astTrVari ) ){
			if ( Tr_PathIsInLoop() ){
				if( !Tr_VariIsLoopCnter( astTrVari ) ){
					if( tr_RecIsRecursive( astTrVari, stCmdCurrTraceInfo.astTable ) ){
						Tr_VariResetScope( astTrVari );
						tr_ResLoggingRestore( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_INLOOP_RESTORE );
					}else{
						astOperand = LinkCommandList.getRightOperand( stCmdCurrTraceInfo.astTable );
						Tr_ScpGetOperandValue( astOperand, &scp );
						Tr_ScpAdjustType( &scp, LinkVariable.getType( astTempVari ));
						Tr_VariSetScope( astTrVari, &scp );
						tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
					}
				}else{
					astOperand = LinkCommandList.getRightOperand( stCmdCurrTraceInfo.astTable );
					Tr_ScpGetOperandValue( astOperand, &scp );
					Tr_ScpAdjustType( &scp, LinkVariable.getType( astTempVari ));
					Tr_VariSetScope( astTrVari, &scp );
					tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
				}
			}else{
				astOperand = LinkCommandList.getRightOperand( stCmdCurrTraceInfo.astTable );
				Tr_ScpGetOperandValue( astOperand, &scp );
				Tr_ScpAdjustType( &scp, LinkVariable.getType( astTempVari ));
				Tr_VariSetScope( astTrVari, &scp );
				tr_ResLoggingNewScope( stCmdCurrTraceInfo.astTable, astTempVari, VARI_CHANGED_BY_ASSIGN, &scp, NULL );
			}
		}
	}
	return TRACEEXIT_SUCCESS;
}
static VOID tr_RecLimitVariByGreater( AST astTrVari, TRVALUESCP *pVarScope, BOOL bEqual ){
	TRVALUESCP variScope;
	TRVALUESCP result;
	AST astType = LinkVariable.getType( stTrVariableAccess.variable.get( astTrVari ));
	Tr_VariGetScope( astTrVari, &variScope );
	Tr_ScpLimitScopeByGreater( &variScope, pVarScope,&result, bEqual );
	Tr_ScpAdjustType( &result, astType );
	Tr_VariSetScope( astTrVari, &result );

	Tr_VariGetNegationScope( astTrVari, &variScope );
	Tr_ScpLimitScopeByLess( &variScope, pVarScope,&result, !bEqual );
	Tr_ScpAdjustType( &result, astType );
	Tr_VariSetNegationScope( astTrVari, &result );
}
static VOID tr_RecLimitVariByLess( AST astTrVari, TRVALUESCP *pVarScope, BOOL bEqual ){
	TRVALUESCP variScope;
	TRVALUESCP result;
	AST astType = LinkVariable.getType( stTrVariableAccess.variable.get( astTrVari ));
	Tr_VariGetScope( astTrVari, &variScope );
	Tr_ScpLimitScopeByLess( &variScope, pVarScope,&result, bEqual );
	Tr_ScpAdjustType( &result, astType );
	Tr_VariSetScope( astTrVari, &result );

	Tr_VariGetNegationScope( astTrVari, &variScope );
	Tr_ScpLimitScopeByGreater( &variScope, pVarScope,&result, !bEqual );
	Tr_ScpAdjustType( &result, astType );
	Tr_VariSetNegationScope( astTrVari, &result );
}
static VOID tr_RecLimitedByRelation( AST  astCmdList  ){
	AST astOperand;
	AST astTrVari;
	TRVALUESCP varScope;
	TRVALUESCP varScope2;
	switch( stCmdListAccess.opKind.get( astCmdList )){
	case ASM_CMD_GREATER:
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByGreater( astTrVari, &varScope, FALSE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList,
						stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByLess( astTrVari, &varScope, FALSE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		break;
	case ASM_CMD_GREATEREQUAL:
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByGreater( astTrVari, &varScope, TRUE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByLess( astTrVari, &varScope, TRUE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		break;
	case ASM_CMD_LESS:
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByLess( astTrVari, &varScope, FALSE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByGreater( astTrVari, &varScope, FALSE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		break;
	case ASM_CMD_LESSEQUAL:
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByLess( astTrVari, &varScope, TRUE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_ScpGetOperandValue( astOperand, &varScope );
				tr_RecLimitVariByGreater( astTrVari, &varScope, TRUE );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari )
						, VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
		break;
	default:
		break;
	}
}
static VOID tr_RecLimitedByLogic( AST astCmdList ){
	AST astBlk1;
	AST astBackupBlk;
	AST astOperand1;
	AST astOperand2;
	if( ASM_CMD_LGAND == stCmdListAccess.opKind.get( astCmdList )){
		astBlk1 = Tr_PathParamCopyNew( stCmdCurrTraceInfo.astPathParam );
		astOperand1 = LinkCommandList.getLeftOperand( astCmdList );
		astOperand2 = LinkCommandList.getRightOperand( astCmdList );
		astBackupBlk = stCmdCurrTraceInfo.astPathParam;
		if( LinkOperand.isCommandList( astOperand1 )){
			astCmdList = LinkOperand.getParameter( astOperand1 );
			stCmdCurrTraceInfo.astPathParam = astBlk1;
			tr_RecLimitedScp( astCmdList );
		}
		if( LinkOperand.isCommandList( astOperand2 )){
			astCmdList = LinkOperand.getParameter( astOperand2 );
			stCmdCurrTraceInfo.astPathParam = astBackupBlk;
			tr_RecLimitedScp( astCmdList );
		}
		Tr_PathParamAndMergeTo( astBlk1, stCmdCurrTraceInfo.astPathParam );
	}else{
		astBlk1 = Tr_PathParamCopyNew( stCmdCurrTraceInfo.astPathParam );
		astOperand1 = LinkCommandList.getLeftOperand( astCmdList );
		astOperand2 = LinkCommandList.getRightOperand( astCmdList );
		astBackupBlk = stCmdCurrTraceInfo.astPathParam;
		if( LinkOperand.isCommandList( astOperand1 )){
			astCmdList = LinkOperand.getParameter( astOperand1 );
			stCmdCurrTraceInfo.astPathParam = astBlk1;
			tr_RecLimitedScp( astCmdList );
		}
		if( LinkOperand.isCommandList( astOperand2 )){
			astCmdList = LinkOperand.getParameter( astOperand2 );
			stCmdCurrTraceInfo.astPathParam = astBackupBlk;
			tr_RecLimitedScp( astCmdList );
		}
		Tr_PathParamOrMergeTo( astBlk1, stCmdCurrTraceInfo.astPathParam );
	}
}
static VOID tr_RecLimitedByEqually( AST astCmdList ){
	AST astOperand;
	AST astTrVari;
	TRVALUESCP varScope;
	TRVALUESCP varScope2;

	if( ASM_CMD_EQUAL == stCmdListAccess.opKind.get( astCmdList )){
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_ScpGetOperandValue( astOperand, &varScope2 );
				Tr_ScpMergeAndAnd(&varScope, &varScope2, &varScope  );
				Tr_VariSetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList,
						stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}

		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_VariGetScope( astTrVari, &varScope );
				Tr_ScpGetOperandValue( astOperand, &varScope2 );
				Tr_ScpMergeAndAnd(&varScope, &varScope2, &varScope  );
				Tr_VariSetScope( astTrVari, &varScope );
				Tr_VariGetNegationScope( astTrVari, &varScope2 );

				tr_ResLoggingNewScope( astCmdList, stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope, &varScope2 );
			}
		}
	}else{
		astOperand = LinkCommandList.getLeftOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getRightOperand( astCmdList );
				Tr_VariGetNegationScope( astTrVari, &varScope );
				Tr_ScpGetOperandValue( astOperand, &varScope2 );
				Tr_ScpMergeAndAnd(&varScope, &varScope2, &varScope  );
				Tr_VariSetNegationScope( astTrVari, &varScope );
				Tr_VariGetScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList,
						stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope2, &varScope );
			}
		}

		astOperand = LinkCommandList.getRightOperand( astCmdList );
		astTrVari = Tr_OpeGetTraceVari( astOperand );
		if( astTrVari > 0 ){
			if( Tr_VariNeedCalcuteScp( astTrVari ) ){
				astOperand = LinkCommandList.getLeftOperand( astCmdList );
				Tr_VariGetNegationScope( astTrVari, &varScope );
				Tr_ScpGetOperandValue( astOperand, &varScope2 );
				Tr_ScpMergeAndAnd(&varScope, &varScope2, &varScope  );
				Tr_VariSetNegationScope( astTrVari, &varScope );
				Tr_VariGetScope( astTrVari, &varScope2 );
				tr_ResLoggingNewScope( astCmdList,
						stTrVariableAccess.variable.get( astTrVari ),
						VARI_CHANGED_BY_RELATION,
						&varScope2, &varScope );
			}
		}
	}
}
static VOID tr_RecLimitedByNegation( AST astCmd ){
	AST astOperand;
	AST astList;
	astOperand = LinkCommandList.getLeftOperand( astCmd );
	if( LinkOperand.isCommandList( astOperand )){
		astList = LinkOperand.getParameter( astOperand );
		tr_RecLimitedScp( astList );
		Tr_VarBlkReverse( Tr_PathParamGetCurrVariBlock() );
	}
}
static VOID tr_RecLimitedScp( AST astCmd ){
	switch( stCmdListAccess.opKind.get( astCmd )){
	case ASM_CMD_GREATER   :
	case ASM_CMD_GREATEREQUAL   :
	case ASM_CMD_LESS   :
	case ASM_CMD_LESSEQUAL   :
		tr_RecLimitedByRelation( astCmd );
		break;
	case ASM_CMD_EQUAL   :
	case ASM_CMD_UNEQUAL   :
		tr_RecLimitedByEqually( astCmd );
		break;
	case ASM_CMD_LGAND   :
	case ASM_CMD_LGOR   :
		tr_RecLimitedByLogic( astCmd );
		break;
	case ASM_CMD_NEGATION :
		tr_RecLimitedByNegation( astCmd );
		break;
	default:
		break;
	}
}
static S4 tr_RecCmdList_Judge( VOID ){
	AST astOperand;
	AST astList;
	Tr_VarBlkCopyNegationScp( Tr_PathParamGetCurrVariBlock() );
	astOperand = LinkCommandList.getLeftOperand( stCmdCurrTraceInfo.astTable );
	if( LinkOperand.isCommandList( astOperand )){
		astList = LinkOperand.getParameter( astOperand );
		tr_RecLimitedScp( astList );
	}
	return TRACEEXIT_SUCCESS;
}
static S4 tr_RecCmdList( AST astCmdList ){
	U4 kind = stCmdListAccess.opKind.get( stCmdCurrTraceInfo.astTable );
	S4 rc = TRACEEXIT_SUCCESS;
	TRY;
	switch(kind){
	case ASM_CMD_RETURN  :
		rc = tr_RecCmdList_Ret();
		break;
	case ASM_CMD_GETOPERAND  :
		rc = tr_RecCmdList_Primary();
		break;
	case ASM_CMD_GETOFFSET_UNIT   :
	case ASM_CMD_GETOFFSET    :
		/* only read address. no read, no write, skip */
		break;
	case ASM_CMD_GETMEMDATA   :
	case ASM_CMD_GETADDR  :
	case ASM_CMD_MINUS  :
	case ASM_CMD_NEGATION :
	case ASM_CMD_BITNEGATION :
		rc = tr_RecCmdList_Unary();
		break;
	case ASM_CMD_CALL  :
		/* only read address. do not deal with arguments, skip  */
		break;
	case ASM_CMD_INC  :
		rc = tr_RecCmdList_Inc();
		break;
	case ASM_CMD_DEC  :
		rc = tr_RecCmdList_Dec();
		break;
	case ASM_CMD_CAST   :
		/* read. skip */
		break;
	case ASM_CMD_MUL   :
	case ASM_CMD_DIV   :
	case ASM_CMD_MOD   :
	case ASM_CMD_ADD  :
	case ASM_CMD_SUB  :
		/* read. skip */
		break;
	case ASM_CMD_LSFT   :
	case ASM_CMD_RSFT   :
		/* read. skip */
		break;
	case ASM_CMD_GREATER   :
	case ASM_CMD_GREATEREQUAL   :
	case ASM_CMD_LESS   :
	case ASM_CMD_LESSEQUAL   :
		/* read. skip */
		break;
	case ASM_CMD_EQUAL   :
	case ASM_CMD_UNEQUAL   :
		/* read. skip */
		break;
	case ASM_CMD_BITAND   :
	case ASM_CMD_BITEXOR   :
	case ASM_CMD_BITINOR  :
		/* read. skip */
		break;
	case ASM_CMD_LGAND   :
	case ASM_CMD_LGOR   :
		/* read. skip */
		break;
	case ASM_CMD_ASSIGN   :
		rc = tr_RecCmdList_Assign();
		break;
	case ASM_CMD_ASSIGNARG   :
		/* read. skip */
		break;
	case ASM_CMD_JUDGE  :
		rc = tr_RecCmdList_Judge();
		break;
	default:
		//	case ASM_CMD_NOP   :
		//	case ASM_CMD_CHOOSE :
		//	case ASM_CMD_CHOOSEEND :
		//	case ASM_CMD_CONFLUX  :
		//	case ASM_CMD_JUMP  :
		//	case ASM_CMD_JUDGE  :
		//	case ASM_CMD_BRANCH  :
		//	case ASM_CMD_FUNCENTRY  :
		//	case ASM_CMD_FUNCEXIT   :
		/* no effect. skip */
		break;
	}
	CATCH(TRACEEXIT_FATAL);
	return rc;
}
S4 Tr_RecInfo( AST astCmdList, U4 event ){
	S4 rc = TRACEEXIT_SUCCESS;
	if( stCmdTraceOption.ulCmdEvent & event ){
		if( stCmdTraceOption.pCallBackFunction != NULL ){
			stCmdTraceOption.pCallBackFunction( stCmdCurrTraceInfo.astTable, event );
		}
	}
	if( event == EVENT_CMDLIST_PREV ){
		if( stCmdTraceOption.ucRecordValue ){
			return tr_RecCmdList(astCmdList);
		}
	}
	return rc;
}
